﻿using CATLTempUpdate.CommonLib;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace CATLTempUpdate.TcpServer
{
    public  class CRCCheck
    {
        ///<param name = "crcHead" >包头</ param >
        ///<param name = "upOrDown" >上、下行或应答报文</ param >
        ///<param name = "crcTail" >包尾</ param >
        ///<param name="arrayVal">数组校验码</param>
        ///<param name="crcVal">报文校验码</param>
        ///<param name="crcTrueOrFalse">校验码是否正确</param>
        ///<param name="senseCodeId">基板ID</param>
        ///<param name="senseCodeType">基板类型</param>
        ///<param name="dataLength">数据包长</param>
        ///<param name="answerType">应答类型</param>
        ///<param name="answerData">应答报文</param>
        public string crcHead = string.Empty, crcTail = string.Empty, arrayVal = string.Empty, crcVal = string.Empty,
        answerType = string.Empty, answerData = string.Empty;
        ///dataIo = string.Empty;
        
        public Byte[] Packdata;
        public int senseCodeId, senseCodeType, upOrDown,PacType;
        public bool crcTrueOrFalse = false;

        public CRCCheck(List<byte> bufferData)
        {
            #region 解析报文
            if (bufferData.Count > 0)
            {
                int dataLength = 0;
                bufferData.Insert(0,126);
                crcHead = bufferData[0].ToString("X2");//包头
                upOrDown = Convert.ToInt32(bufferData[1]);//上、下行或应答报文
                senseCodeId = Hex16To10(bufferData[2].ToString("X2") + bufferData[3].ToString("X2"));//基板ID
                PacType = Hex16To10(bufferData[4].ToString("X2"));                                 //报文类型
                dataLength = Hex16To10(bufferData[5].ToString("X2") + bufferData[6].ToString("X2"));//数据包长
                
                
                Int16 crcint = CRCCode(bufferData.ToArray(), dataLength + 7);
                arrayVal = Convert.ToString(crcint, 16).ToUpper();//获取数组校验码
                if (arrayVal.Length == 1)
                {
                    arrayVal = "000" + arrayVal;
                }
                if (arrayVal.Length == 2)
                {
                    arrayVal = "00" + arrayVal;
                }
                if (arrayVal.Length == 3)
                {
                    arrayVal = "0" + arrayVal;
                }
                //判断校验码
                crcVal = bufferData[dataLength + 8].ToString("X2") + bufferData[dataLength + 7].ToString("X2");//获取报文校验码
                if (PacType != 0)
                {
                    if (PacType == 15)
                    {
                        lock (FormTemperatureStocking.ChangeTimeLock)
                        {
                            try
                            {
                                DataRow[] AliveDr = TempCanData.AliveTraceDt.Select("SenseId=" + senseCodeId);
                                if (AliveDr.Length > 0)
                                {
                                    AliveDr[0]["ChangeTime"] = DateTime.Now;
                                }
                            }
                            catch (Exception ex)
                            {
                                Log.AddLog(LogFile.SystemError,"更新心跳失败"+ex.Message);
                            }
                            
                        }
                        
                    }
                    //Log.AddLog(LogFile.SystemError,"收到TM的应答Pack,IP为："+ IP + ",:"+ bufferData.Count + "," + ":" + string.Join("-", bufferData.ToArray()));
                }
                if (arrayVal == crcVal)
                {
                    crcTrueOrFalse = true;
                    if (upOrDown == 0)
                    {
                        senseCodeType = Convert.ToInt32(bufferData[4]);//基板类型 
                        int numColumn = dataLength;
                        if (senseCodeType == 0)
                        {
                            numColumn = 96;
                        }
                        try
                        {
                            for (int i = 0; i < 24; i++)
                            {
                                int countNum = 7 + i * 4;//起始数组位置
                                byte[] ChTemp = new byte[4];
                                for (int m = 0; m < 4; m++)
                                {
                                    ChTemp[m] = bufferData[countNum + m];
                                }
                                float ChnoTemp = BitConverter.ToSingle(ChTemp, 0);
                                if (ChnoTemp > 0)
                                {
                                    if (SenseDataCollection.IfShowSenseData)
                                    {
                                        if (FormTemperatureStocking.ShowSenseCodeId == senseCodeId)
                                        {
                                            try
                                            {
                                                if ((i + 1) <= 18)
                                                {
                                                    DataRow[] TempDr = TempCanData.TempDt.Select("chno=" + (i + 1));
                                                    if (TempDr.Length > 0)
                                                    {
                                                        TempDr[0]["temp"] = ChnoTemp.ToString("0.0");
                                                    }
                                                }

                                            }
                                            catch (Exception ex)
                                            {
                                                Log.AddLog(LogFile.SystemError, "将基板" + senseCodeId + "通道" + (i + 1) + "的温度更新到展示DT失败" + ex.Message);
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    //Log.AddLog(LogFile.MeasureError, "[Warning]基板" + senseCodeId + "通道" + (i + 1) + "的温度异常，异常温度为" + ChnoTemp + "原始报文为" + string.Join("-", bufferData.ToArray()));
                                }
                                if (ChnoTemp > 80)
                                {
                                    Log.AddLog(LogFile.MeasureError, "[Warning]基板" + senseCodeId + "通道" + (i + 1) + "的温度异常，异常温度为" + ChnoTemp + "原始报文为" + string.Join("-", bufferData.ToArray()));
                                }
                                
                                //将数据更新到List中
                                int ColumnNo = (int)Math.Ceiling((Convert.ToDecimal(senseCodeId) / 4));
                                int RowNo = senseCodeId % 4;
                                if (RowNo == 0)
                                {
                                    RowNo = 3;
                                }else
                                {
                                    RowNo = RowNo - 1;
                                }
                                if (ChnoTemp>0)
                                {
                                    SenseDataCollection.TempDataList[ColumnNo - 1][RowNo][i] = Convert.ToInt32((ChnoTemp * 10));
                                }

                            }
                            
                        }
                        catch (Exception ex)
                        {
                            Log.AddLog(LogFile.SystemError,"解析数据失败"+ex.Message);
                        }
                    }
                }
                else
                {
                    Log.AddLog(LogFile.Trace, "CRC校验失败:" + string.Join("-", bufferData.ToArray()));
                }
                //crcTail = bufferData[dataLength + 9].ToString("X2");//包头尾
            }
            #endregion
        }
        
        /// <summary>
        /// CRC高位校验码checkCRCHigh
        /// </summary>
        static byte[] ArrayCRCHigh =
            {
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
        0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
        0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
        0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
        0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
        };
        /// <summary>
        /// CRC地位校验码checkCRCLow
        /// </summary>
        static byte[] checkCRCLow =
        {
        0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
        0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
        0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
        0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
        0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
        0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
        0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
        0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
        0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
        0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
        0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
        0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
        0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
        0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
        0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
        0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
        0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
        0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
        0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
        0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
        0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
        0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
        0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
        0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
        0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
        0x43, 0x83, 0x41, 0x81, 0x80, 0x40
        };
        /// <summary>
        /// CRC校验
        /// </summary>
        /// <param name="data">校验的字节数组</param>
        /// <param name="length">校验的数组长度</param>
        /// <returns>该字节数组的校验码</returns>
        public static Int16 CRCCode(byte[] data, int arrayLength)
        {
            byte CRCHigh = 0xFF;
            byte CRCLow = 0xFF;
            byte index;
            int i = 0;
            while (arrayLength-- > 0)
            {
                index = (System.Byte)(CRCHigh ^ data[i++]);
                CRCHigh = (System.Byte)(CRCLow ^ ArrayCRCHigh[index]);
                CRCLow = checkCRCLow[index];
            }
            return (Int16)(CRCHigh << 8 | CRCLow);
        }
        /// <summary>
        /// 16进制转换为10进制
        /// </summary>
        /// <param name="strVal16">十六进制数</param>
        /// <returns>返回十进制数</returns>
        public static int Hex16To10(string strVal16)
        {
            return Convert.ToInt32(strVal16, 16);
        }
        /// <summary>
        /// 10进制转换为16进制
        /// </summary>
        /// <param name="strVal10">十进制数</param>
        /// <returns>返回十六进制数</returns>
        public static string Hex10To16(int strVal10)
        {
            return strVal10.ToString("X");
        }

        /// <summary>
        /// 接收到上传的打包数据后，按照相反的过程进行还原原数据
        /// </summary>
        /// <param name="source">待解析的源数据</param>
        /// <param name="slength">待解析数据字节个数</param>
        /// <param name="dest">还原后的原数据</param>
        /// <param name="dlength">还原后的数据字节长度</param>
        public static void DecryptData(List<byte> sourcelist, int slength, out List<byte> dest, out int dlength)
        {
            if (sourcelist.IndexOf(125) < 0)
            {
                dest = sourcelist;
                dlength = dest.Count;
                return;
            }
            else
            {
                byte[] source = sourcelist.ToArray();
                List<byte> dests = new List<byte>();
                for (int i = 0; i < source.Length; i++)
                {
                    if (source[i] == 0x7D)
                    {
                        if (source[i + 1] == 0x5E)
                        {
                            dests.Add(0x7E);
                        }
                        else if (source[i + 1] == 0x5D)
                        {
                            dests.Add(0x7D);
                        }
                        i++;
                    }
                    else
                    {
                        dests.Add(source[i]);
                    }
                }
                dlength = dests.Count;
                dest = new List<byte>();
                dest = dests;
                //dests.CopyTo(dest);
            }

        }
    }
}